package cn.itcast.hotel;

import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


import java.io.IOException;
import java.util.Map;

@Slf4j
@SpringBootTest
public class HotelDocumentTest02 {
    @Autowired
    IHotelService hotelService;
    private RestHighLevelClient client;

    @BeforeEach
    public void init(){
        this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://47.100.216.179:9200")));
    }
    @AfterEach
    public void end() throws IOException {
        this.client.close();
    }

    @Test
    public void testMatchAll() throws IOException {
        // 1.创建请求
        SearchRequest request = new SearchRequest("hotel");
        // 2.执行请求方法
        request.source().query(QueryBuilders.matchAllQuery());
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 3.获取结果
//        System.out.println(response.getHits().getTotalHits());
        resultParse(response);

    }

    private void resultParse(SearchResponse response) {
        log.warn("总数为{}",response.getHits().getTotalHits());
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String jsonStr = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(jsonStr, HotelDoc.class);
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (!highlightFields.isEmpty()){
                HighlightField field = highlightFields.get("name");
                if (field != null){
                    String name = field.getFragments()[0].string();
                    hotelDoc.setName(name);
                }
            }
            log.warn("结果信息为{}",hotelDoc);
        }
    }

    @Test
    public void testMatch() throws IOException {
        // 1.创建请求
        SearchRequest request = new SearchRequest("hotel");
        // 2.执行请求方法
        request.source().query(QueryBuilders.matchQuery("name","外滩地铁"));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 3.获取结果
        log.warn("总数为{}",response.getHits().getTotalHits());
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String jsonStr = hit.getSourceAsString();
            log.warn("结果信息为{}",jsonStr);
        }
    }
    @Test
    public void testTerm() throws IOException {
        // 1.创建请求
        SearchRequest request = new SearchRequest("hotel");
        // 2.执行请求方法
        request.source().query(QueryBuilders.termQuery("city","杭州"));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 3.获取结果
        resultParse(response);
    }
    @Test
    public void testRange() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        request.source().query(QueryBuilders.rangeQuery("price").gte(333).lte(555));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        resultParse(response);
    }
    @Test
    public void testBool() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchQuery("name","外滩明珠"));
        // should与must连用，should将会失效
        boolQueryBuilder.should(QueryBuilders.termQuery("brand","速8"));
//        boolQueryBuilder.should(QueryBuilders.termQuery("brand","7天酒店"));
//                .mustNot(QueryBuilders.rangeQuery("price").lte(250));
        request.source().query(boolQueryBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        resultParse(response);
    }
    @Test
    public void testSortAndPage() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        int page = 3;
        int size = 5;
        request.source().from((page-1)*size);
        request.source().size(size);
        request.source().query(QueryBuilders.geoDistanceQuery("location").distance(20, DistanceUnit.KILOMETERS).point(new GeoPoint("31.040607,121.619015")));
        request.source().sort("price", SortOrder.DESC);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        resultParse(response);
    }

    @Test
    public void testHighLight() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
//        int page = 3;
//        int size = 5;
//        request.source().from((page-1)*size);
//        request.source().size(size);
        request.source().query(QueryBuilders.matchQuery("all","上海"));
        request.source().query(QueryBuilders
                .geoDistanceQuery("location")
                .distance(20, DistanceUnit.KILOMETERS).point(new GeoPoint("31.040607,121.619015")));
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<span>");
        highlightBuilder.postTags("</span>");
        highlightBuilder.field("name");
        highlightBuilder.requireFieldMatch(false);
        request.source().highlighter(highlightBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        resultParse(response);

    }
    @Test
    public void testFunction(){
        SearchRequest request = new SearchRequest("hotel");
        request.source().query(QueryBuilders.rangeQuery("price").gte(250).lte(550));

    }
}
